//
//  StatusDAL.swift
//  我的微博
//
//  Created by mac on 15/8/12.
//  Copyright © 2015年 szh. All rights reserved.
//

import Foundation

/// 数据库缓存时间长度
private let dbCacheDateTime: NSTimeInterval = 60 // 1 * 24 * 3600

class StatusDAL {
    
    /// 清除数据库缓存数据
    /// 提示：删除数据，本身不会让数据库变小，数据库会保留空间，出于性能考虑，数据缓存时间不适合太长
    /// 注意，不要将太大的二进制数据(无法检索)保存在数据库中
    class func clearDatabaseCache() {
        // 1. 确定删除缓存的日期
        let date = NSDate(timeIntervalSinceNow: -dbCacheDateTime)
        // 转换日期格式
        let df = NSDateFormatter()
        df.locale = NSLocale(localeIdentifier: "en")
        df.dateFormat = "yyyy-MM-dd HH:mm:ss"
        let dateString = df.stringFromDate(date)
        
        print(dateString)
        
        // 2. 执行清除缓存的代码
        /*
            -- 测试删除语句时，先用 SELECT 确认满足条件的记录能否被查到
            -- 如果直接用 DELETE 会看不到结果，而且容易误删除数据
        */
        let sql = "DELETE FROM T_Status WHERE createTime < '\(dateString)';"
        
        SQLiteManager.sharedManager.queue.inDatabase { (db) -> Void in
            db.executeUpdate(sql)
            print("删除成功")
        }
    }
    
    /// 数据访问层加载数据
    /// 从数据库&网络加载
    class func loadStatus(since_id: Int, max_id: Int, finished: (array: [[String: AnyObject]]?, error: NSError?)->()) {
        
        // 1. 检查本地是否有缓存数据
        loadCacheData(since_id, max_id: max_id) { (array) -> () in
            
            // 2. 如果有缓存数据，直接返回
            if (array?.count ?? 0) > 0 {
                finished(array: array, error: nil)
                return
            }
            
            // 3. 如果没有缓存，加载网络数据
            NetworkTools.sharedTools.loadStatus(since_id, max_id: max_id, finished: { (result, error) -> () in

                /// 判断能否获得字典数组
                if let array = result?["statuses"] as? [[String: AnyObject]] {
                    
                    // 4. 加载完成后，将数据保存至`数据库`
                    saveStatus(array)
                    
                    // 5. 完成回调
                    finished(array: array, error: nil)
                } else {
                    finished(array: nil, error: error)
                }
            })
        }
    }
    
    /// 加载缓存数据
    /// 1. 确定参数 since_id 下拉刷新 max_id 上拉刷新
    /// 2. 确定 SQL
    /// 3. 执行 SQL，返回数据
    class func loadCacheData(since_id: Int, max_id: Int, finished: (array: [[String: AnyObject]]?)->()) {
        
        // 判断用户是否登录
        assert(UserAccount.userLogon, "必须登录才能调用")
        
        let userId = UserAccount.sharedAccount!.uid!
        
        var sql = "SELECT statusId, status, userId FROM T_Status \n" +
        "WHERE userId = \(userId) \n"
            
        // 根据参数，调整查询条件
        if since_id > 0 {       // 下拉刷新
            sql += "AND statusId > \(since_id) \n"
        } else if max_id > 0 {  // 上拉刷新
            sql += "AND statusId < \(max_id) \n"
        }
        sql += "ORDER BY statusId DESC LIMIT 20;"
        
        // 继续之前，一定记住测试
        print(sql)
        
        SQLiteManager.sharedManager.queue.inDatabase { (db) -> Void in
            guard let rs = db.executeQuery(sql) else {
                // 空数据的回调
                finished(array: nil)
                return
            }
            
            // 生成查询结果内容 - 返回什么样的结果 -> 字典的数组
            var array = [[String: AnyObject]]()
            while rs.next() {
                let jsonString = rs.stringForColumn("status")
                // 反序列化
                let dict = try! NSJSONSerialization.JSONObjectWithData(jsonString.dataUsingEncoding(NSUTF8StringEncoding)!, options: NSJSONReadingOptions(rawValue: 0))
                
                // 将字典插入数组
                array.append(dict as! [String: AnyObject])
            }
            
            // 通过回调返回数据
            finished(array: array)
        }
    }
    
    /// 将数据保存到数据库
    /// 1. 确定一下参数 - 从网络获取到的`字典`数组
    /// 2. 确定 SQL
    /// 3. 利用数据库工具，遍历数组，顺序插入数据
    class func saveStatus(array: [[String: AnyObject]]) {
        
        // 判断用户是否登录
        assert(UserAccount.userLogon, "必须登录才能调用")
        
        /*
            1. 字段中一定要有主键
            2. 主键一定不是自动增长的，如果是自动增长，INSERT 的时候，无法确定主键
        */
        let sql = "INSERT OR REPLACE INTO T_Status (statusId, status, userId) VALUES (?, ?, ?);"
        
        let userId = UserAccount.sharedAccount!.uid!
        
        SQLiteManager.sharedManager.queue.inTransaction { (db, rollback) -> Void in
            
            // 1. 遍历数组
            for dict in array {
                // 1> 微博代号
                let statusId = dict["id"] as! Int
                // 2> status 是 字典对应的 JSON 字符串，序列化
                let json = try! NSJSONSerialization.dataWithJSONObject(dict, options: NSJSONWritingOptions.PrettyPrinted)
                let jsonString = NSString(data: json, encoding: NSUTF8StringEncoding)!
                
                // 3> 插入数据
                if !db.executeUpdate(sql, statusId, jsonString, userId) {
                    rollback.memory = true
                    break
                }
            }
            // 2. 输出结果
            print("保存了 \(array.count) 条记录")
        }
    }
}